import {GameEvent} from "db://assets/script/game-event";
import {director} from "cc";
import {http} from "db://assets/script/common/HTTP";
import {lobby} from "db://assets/script/lobby";
import Long from "long";
import {cmm} from "db://assets/script/utils/cmm";
import {AssetCoreChange} from "db://assets/script/common/events/asset-events/asset-core-change";
import {
    MixMixRequest,
    MixMixResult, MixPipesResult,
    MixPipesResult_MixInfo,
    MixReceiveRequest,
    MixReceiveResult
} from "db://assets/proto/new-world-api/v1/mix";
import {mixingConfigsLoader} from "db://assets/script/configs/mixing-configs-loader";
import {MixingReceive} from "db://assets/script/common/events/mix-events/mixing-receive";
import {MixingMix} from "db://assets/script/common/events/mix-events/mixing-mix";


export class UserMixingInfo {
    private mixInfos: { [k: string]: MixPipesResult_MixInfo } = {};
    private _receiveCallback: Map<string, (uniqueId: Long) => void> = new Map(
        [
            ["pipe_tag:building", (uniqueId: Long) => director.emit(GameEvent.uiUpdateCity, uniqueId)]
        ]
    );


    start() {
        this.onRequestEvent()
    }


    onRequestEvent() {
        director.on(GameEvent.mixingMix, this._requestMix, this)
        director.on(GameEvent.mixingTryReceive, this._requestReceive, this)
    }

    loadMixInfo(pipeTag: string, uniqueId: Long) {
        return this.mixInfos[pipeTag + ':' + uniqueId.toString()]
    }

    setMixInfos(mixInfos: { [k: string]: MixPipesResult_MixInfo }) {
        this.mixInfos = mixInfos
    }

    setMixInfo(pipeTag: string, uniqueId: Long, info: MixPipesResult_MixInfo) {
        this.mixInfos[pipeTag + ':' + uniqueId.toString()] = info
    }

    _requestMix(event: MixingMix) {
        const param = MixMixRequest.create({
            uniqueId: event.uniqueId,
            pipeTag: event.pipeTag,
            mixNum: event.produceNum,
        })
        http.requestAsync('POST', 'v1/mixing/mix', MixMixResult, MixMixRequest.encode(param).finish())
            .then(resp => {
                const uniquePipeTag = event.pipeTag + ':' + event.uniqueId
                director.emit(GameEvent.assetCoreChange, new AssetCoreChange(event.costAsset));
                this.mixInfos[uniquePipeTag] = MixPipesResult_MixInfo.create({
                    num: event.produceNum,
                    received: 0,
                    completeAtMs: resp.completeAtMs,
                    beginAtMs: resp.beginAtMs,
                    beginAtMsOffset: 0,
                })
                lobby.instance.showToast('开始生产')
                this._callback(event.pipeTag, event.uniqueId)
            })
            .catch(err => console.log(err))
    }

    _requestReceive(event: MixingReceive) {
        const param = MixReceiveRequest.create({
            uniqueId: event.uniqueId,
            pipeTag: event.pipeTag,
        })
        http.requestAsync('POST', 'v1/mixing/receive', MixReceiveResult, MixReceiveRequest.encode(param).finish())
            .then(resp => {
                const mpc = mixingConfigsLoader.findMixPipeConfig(event.pipeTag, event.level)
                const formula = mixingConfigsLoader.findMixFormulaConfig(mpc!.formulaId)
                if (formula) {
                    const mixedNum = resp.success.length
                    const assets = cmm.map2kv(resp.assets, (k1, v1) => {
                        return {
                            k2: k1.toNumber(),
                            v2: v1,
                        }
                    })
                    const uniquePipeTag = event.pipeTag + ':' + event.uniqueId
                    const info = this.mixInfos[uniquePipeTag]!
                    if (formula.input.length == 0) {
                        info.completeAtMs = info.beginAtMsOffset.add(info.beginAtMsOffset).add(mixedNum * formula.costMs.toNumber()).add(mpc!.maxProduce * formula.costMs.toNumber())
                        info.beginAtMsOffset = Long.fromNumber(0)
                        info.received = Long.fromNumber(0)
                    } else {
                        info.completeAtMs = info.completeAtMs.sub(formula.costMs.mul(mixedNum))
                        info.beginAtMsOffset = info.beginAtMsOffset.add(formula.costMs.mul(mixedNum))
                        info.received = info.received.add(mixedNum)
                    }
                    director.emit(GameEvent.assetCoreChange, new AssetCoreChange(assets));
                    lobby.instance.showAssetGainToast(assets)
                    this._callback(event.pipeTag, event.uniqueId)
                }
            })
            .catch(err => console.log(err))
    }

    private _callback(pipeTag: string, uniqueId: Long) {
        const tmp = pipeTag.replace('pipe_tag:', '')
        const idx = tmp.indexOf(':')
        const typePipeTag = 'pipe_tag:' + tmp.substring(0, idx)
        const callback = this._receiveCallback.get(typePipeTag)
        if (callback) callback(uniqueId)
    }


}

